home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS Toolkit
/
BBS Toolkit.iso
/
ezy_comm
/
ezy1023.zip
/
EKIT102.ZIP
/
EZYUNIT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1992-10-24
|
24KB
|
743 lines
(* This unit is the copyrighted works of Peter Davies 1992.
Peter Davies reserves all rights on this material. Use
of this library is granted freely, however due credit must
be given to Peter Davies. That is, you must mention that
you used source written by Peter Davies. No liability
whatsoever is given for this unit. You accept all
responsibility whatsoever.
You are hereby allowed to modify the source code, but you must NOT
distribute it in modified form. If, you have any enhancements to this
unit for inclusion, please send them to me.
For improvements, please contact Peter Davies Fido 3:633/152 *)
Unit ezyunit;
{$O-,F+,R-,S-,V-}
Interface
uses crt,dos,ezyinc;
type
msgarearecord = record
hdrfile,
txtfile : file;
msgarea : word;
msgrec : messagerecord;
end;
var
msgrecfile : file;
(* Always use this file when accessing MESSAGES.EZY
If, this file is Open EzyUnit will Utilize it. If closed,
Ezycom will Open it, then close it *)
const
Hex : Array[$0..$F] Of Char = '0123456789abcdef';
initializedate : boolean = true;
(* This flags whether the message write routine should initialize
the posttimedate or not (true means it should) *)
echomailentered : boolean = false;
netmailentered : boolean = false;
(* These flags are set if Netmail and/or Echomail were entered
while this program is in operation *)
programname : string[10] = 'EzyUnit';
(* Name of program to place in origin and/or tearline *)
usetearline : boolean = true;
(* true means place the program name in the tearline
false means place the program name in the PID line *)
function fopen(var miscfile : file;recsize : word;fmode : byte;fname : maxstr) : boolean;
(* Opens an UnTyped File, with sharing *)
function openmsgareaforread(area : word; var msgarearec : msgarearecord) : boolean;
(* Opens a Message Area for Reading *)
function openmsgareaforwrite(area : word;var msgarearec : msgarearecord) : boolean;
(* Opens a Message Area for Writing *)
procedure closemsgarea(var msgarearec : msgarearecord);
(* Close a Message Area *)
function writemessage(var msgarearec : msgarearecord;var msghdrrec : msghdrrecord;var msgtxtrec) : word;
(* Writes a Message to an opened msgarea *)
function readmessage(var msgarearec : msgarearecord;
msgtoread : word;
var msghdrrec : msghdrrecord;
var msgtxtrec;maxread : word;
var numread : word) : boolean;
(* Reads a Message from an opened msgarea *)
function retcombinedarea(var lastreadfile : file;
userrecord,
messageboard : word) : boolean;
function retlastread(var lastreadfile : file;
userrecord,
messageboard : word) : word;
(* Returns the lastread pointer for a user in a conference
where : lastreadfile is an untyped file
userrecord is the user record number
messageboard is the message board *)
procedure writelastread(var lastreadfile : file;
userrecord,
messageboard,
lastread : word);
(* Writes the lastread pointer for a user in a conference
where : lastreadfile is an untyped file
userrecord is the user record number
messageboard is the message board
lastread is the last read pointer to write *)
function hexbyte(b : byte) : str2;
(* Returns the Byte in Hexadecimal *)
function hexword(w : word) : str4;
(* Returns the Word in Hexadecimal *)
function hexlong(ww : longint) : str8;
(* Returns the Longint in Hexadecimal *)
function retnetstring(var netinfo : netrecord) : str23;
(* Returns the netaddress in string form *)
function lock(var f : file;pos : word;size : longint) : boolean;
(* Lock a region of the file *)
function unlock(var f : file;pos : word;size : longint) : boolean;
(* Unlock a region of the file *)
procedure getmsgareacount(var msgareacount : msgareacounttype);
(* Get number of messages for each area *)
Implementation
uses ezycrc;
function fopen(var miscfile : file;recsize : word;fmode : byte;fname : maxstr) : boolean;
var
ioerror : word;
filelock : boolean;
ch : char;
timer : boolean;
begin
fname := low2up(fname);
assign(miscfile,fname);
filemode := fmode;
{$I-}
filelock := false;
ch := #0;
timer := false;
repeat
reset(miscfile,recsize);
ioerror := ioresult;
if (ioerror = 5) then
begin
if (not filelock) and (ioerror = 5) then
begin
(* Open a Window
openwindow((80-length(fname))div 2 - 2,10,(80-length(fname))div 2 + 2 + length(fname),14,' File Lock ',
configrec.popuphighlight + configrec.disppopupb * 16,
configrec.disppopupborder + configrec.disppopupb * 16);
textcolor(configrec.disppopupf);
textbackground(configrec.disppopupb);
clrscr;
writeln;
write(' ' + fname);
filelock := true; *)
end;
delay(500);
if keypressed then
begin
ch := readkey;
if (ch = #0) then
ch := readkey;
end;
end else
if (ioerror <> 0) then
begin
if (ioerror = 2) or (ioerror = 3) then
begin
writeln(chr(254) + ' ',fname,' not found');
halt(1);
end;
runerror(ioerror);
end;
until (ioerror = 0) or (ch = #27) or (timer);
{$I+}
(* Close the window
if filelock then
closewindow; *)
fopen := (ch<>#27) and (not timer);
end;
function hexbyte(b : byte) : str2;
begin
hexbyte := hex[b shr 4] + hex[b and $F];
end;
function hexword(w : word) : str4;
begin
hexword := hexbyte(hi(w)) + hexbyte(lo(w));
end;
function hexlong(ww : longInt) : str8;
var
w : array[1..2] of word absolute ww;
begin
hexlong := hexword(w[2]) + hexword(w[1]);
end;
function retnetstring(var netinfo : netrecord) : str23;
var
tmp : str23;
begin
with netinfo do
begin
tmp := itos(zone) + ':' + itos(net) + '/' + itos(node);
if (point > 0) then
tmp := tmp + '.' + itos(point);
end;
retnetstring := tmp;
end;
function openmsgareaforread(area : word;var msgarearec : msgarearecord) : boolean;
var
ioerror : word;
msgrecfilestatus : byte;
begin
msgarearec.msgarea := area;
openmsgareaforread := false;
msgrecfilestatus := 0;
if (filerec(msgrecfile).mode = fmoutput) then
exit;
if (filerec(msgrecfile).mode <> fminput) and
(filerec(msgrecfile).mode <> fminout) then
begin
msgrecfilestatus := 1;
if not fopen(msgrecfile,sizeof(messagerecord),fdenynone + freadonly,
systempath + 'MESSAGES.EZY') then
exit;
end;
seek(msgrecfile,area-1);
blockread(msgrecfile,msgarearec.msgrec,1);
if (msgrecfilestatus = 1) then
close(msgrecfile);
if not (msgarearec.msgrec.typ in [localmail,allmail,echomail,netmail]) or
(area > constant.maxmess) then
exit;
if not find(retmessxxx(area,1)) then
exit;
if not find(retmessxxx(area,2)) then
begin
assign(msgarearec.hdrfile,retmessxxx(area,1));
{$I-}
erase(msgarearec.hdrfile);
ioerror := ioresult;
{$I+}
exit;
end;
if not fopen(msgarearec.hdrfile,sizeof(msghdrrecord),fdenynone + freadwrite,retmessxxx(area,1)) then
exit;
if not fopen(msgarearec.txtfile,1,fdenynone + freadonly,retmessxxx(area,2)) then
begin
close(msgarearec.hdrfile);
exit;
end;
openmsgareaforread := true;
end;
function openmsgareaforwrite(area : word;var msgarearec : msgarearecord) : boolean;
begin
with msgarearec do
if not find(retmessxxx(area,1)) or not find(retmessxxx(area,2)) then
begin
assign(hdrfile,retmessxxx(area,1));
rewrite(hdrfile,1);
close(hdrfile);
assign(txtfile,retmessxxx(area,2));
rewrite(txtfile,1);
close(txtfile);
end;
openmsgareaforwrite := openmsgareaforread(area,msgarearec);
end;
procedure closemsgarea(var msgarearec : msgarearecord);
var
ioerror : word;
begin
{$I-}
close(msgarearec.hdrfile);
ioerror := ioresult;
close(msgarearec.txtfile);
ioerror := ioresult;
{$I+}
end;
(* ********************************************************
** **
** Writes a Message in the Message **
** Database **
** **
******************************************************** *)
function writemessage(var msgarearec : msgarearecord;var msghdrrec : msghdrrecord;var msgtxtrec) : word;
(* To write a message, you MUST initialize EVERY field in msghdr, except for
startposition, recvtimedate and posttimedate.
posttimedate should be initialized if initializedate is set to false
If the message is a reply, then PREVREPLY should point
to this message being replied to, although on RETURN, PREVREPLY might
point to another message.
The function returns 0 if failure.
The function returns the message number (record+1) written if success.
Before calling this function, if replying to a message, that message
header SHOULD be written to DISK, and then READ from DISK after the
reply, as the NEXTREPLY field might have changed (not always if it is
already used!) That is, this function handles REPLY CHAINING!
The MsgTxtRec it limited to a 64k message (65000 bytes).
It should NOT be NULL terminated as this unit will add a NULL
terminator. This unit requires MSGHDR's messagelength to contain
the EXACT length of the message to be written.
The orignet and destnet are initialized. If using netmail, you
must fill out destnet before calling this function, but orignet
will be filled out by this procedure.
Note this procedure only handles 64k messages, but if you write your
own, Ezycom can actually handle messages of ANY length. But, Ezymail
can only handle messages of 32K
200 bytes of free space should always be available in the message
text. That is, if you pass an array of 4096 bytes across, then you
can only use upto 3896 bytes *)
type
msgtxtbuffer = array[1..65000] of char;
var
numwrote : word;
regs : registers;
txtpos : longint;
hdrpos : longint;
msgtmp : msghdrrecord;
tmpfile : file;
tmpboolean : boolean;
msgtxtbuf : msgtxtbuffer absolute msgtxtrec;
procedure changeaccess;
var
ioerror : word;
begin
{$I-}
repeat
reset(msgarearec.txtfile,1);
ioerror := ioresult;
if (ioerror = 5) then
delay(500) else
if (ioerror <> 0) then
runerror(ioerror);
until (ioerror = 0);
{$I+}
end;
procedure makedate;
var
dt : datetime;
junk : word;
begin
if not initializedate then
exit;
getdate(dt.year,dt.month,dt.day,junk);
gettime(dt.hour,dt.min,dt.sec,junk);
msghdrrec.recvtimedate := 0;
packtime(dt,msghdrrec.posttimedate);
end;
procedure domsgid(var msgidline : maxstr);
var
tmpfile : file;
domain : domainstr;
domainlen : byte absolute domain;
Dt : Datetime;
sec100,
junk : word;
temp : string[79];
tmplong : longint;
begin
getdate(dt.year,dt.month,dt.day,junk);
gettime(dt.hour,dt.min,dt.sec,sec100);
msghdrrec.recvtimedate := 0;
packtime(dt,tmplong);
if initializedate then
msghdrrec.posttimedate := tmplong;
msgidline := '';
if not fopen(tmpfile,1,fdenynone + freadonly,systempath + 'CONSTANT.EZY') then
exit;
seek(tmpfile,startofdomain + (msgarearec.msgrec.originaddress - 1)*sizeof(domainstr));
blockread(tmpfile,domain,sizeof(domainstr));
close(tmpfile);
temp := hexlong(tmplong shl 2 + (dt.sec mod 2) shl 1 + (sec100 div 50));
if (domainlen > 0) and (pos(' ',domain) > 0) then
msgidline := chr(1) + 'MSGID: "' +
retnetstring(constant.netaddress[msgarearec.msgrec.originaddress]) +
'@' + domain + '" ' + temp + chr(13) else
begin
msgidline := chr(1) + 'MSGID: ' +
retnetstring(constant.netaddress[msgarearec.msgrec.originaddress]);
if (domainlen > 0) then
msgidline := msgidline + '@' + domain;
msgidline := msgidline + ' ' + temp + chr(13);
end;
end;
procedure addbeginlines;
var
msgidline : string[79];
pidline : string[79];
leadstring : maxstr;
totlen : byte;
loop : word;
begin
pidline := #1 + 'PID: '+programname+' V1.02' + #$D;
domsgid(msgidline);
if usetearline then
leadstring := msgidline else
leadstring := pidline + msgidline;
totlen := length(leadstring);
if (totlen > 0) then
begin
move(msgtxtbuf,msgtxtbuf[totlen+1],msghdrrec.messagelength);
for loop := 1 to totlen do
msgtxtbuf[loop] := leadstring[loop];
inc(msghdrrec.messagelength,totlen);
end;
end;
procedure addendlines;
var
tearline : string[79];
endstring : maxstr;
loop : word;
begin
if usetearline then
tearline := '--- '+programname+' '+constant.version+#$D else
tearline := '---'+#$D;
endstring := tearline + ' * Origin: ';
if (length(msgarearec.msgrec.originline) > 0) then
endstring := endstring + msgarearec.msgrec.originline else
endstring := endstring + configrec.defaultorigin;
endstring := endstring + ' ('+
retnetstring(constant.netaddress[msgarearec.msgrec.originaddress]) +
')' + #$D;
for loop := 1 to length(endstring) do
begin
inc(msghdrrec.messagelength);
msgtxtbuf[msghdrrec.messagelength] := endstring[loop];
end;
end;
procedure addtofastmail;
var
msgfast : msgfastrecord;
loop : word;
begin
msgfast.msgboard := msgarearec.msgarea;
msgfast.msgnumber := filesize(msgarearec.hdrfile);
msgfast.whoto := $FFFFFFFF;
for loop := 1 to length(msghdrrec.whoto) do
msgfast.whoto := updc32(ord(upcase(msghdrrec.whoto[loop])),msgfast.whoto);
if fopen(tmpfile,sizeof(msgfast),fdenywrite + fwriteonly,
configrec.msgpath + 'MSGFAST.BBS') then
begin
seek(tmpfile,filesize(tmpfile));
blockwrite(tmpfile,msgfast,1);
close(tmpfile);
end;
end;
procedure updatemsgcount;
var
tmpword : word;
tmpfile : file;
begin
if fopen(tmpfile,sizeof(word),fdenynone + fwriteonly,
configrec.msgpath + 'MSGCOUNT.BBS') then
begin
tmpword := filesize(msgarearec.hdrfile);
seek(tmpfile,msgarearec.msgarea-1);
blockwrite(tmpfile,tmpword,1);
close(tmpfile);
end;
end;
begin
writemessage := 0;
if (msghdrrec.messagelength > 65000) or (msghdrrec.messagelength = 0) then
exit;
txtpos := filepos(msgarearec.txtfile);
hdrpos := filepos(msgarearec.hdrfile);
filemode := fdenywrite + freadwrite;
changeaccess;
msghdrrec.startposition := filesize(msgarearec.txtfile);
with msgarearec.msgrec do
if (typ in [echomail,netmail]) then
msghdrrec.orignet := constant.netaddress[originaddress];
with msgarearec.msgrec do
if (typ in [localmail,allmail,echomail]) then
begin
msghdrrec.destnet.zone := 0;
msghdrrec.destnet.net := 0;
msghdrrec.destnet.node := 0;
msghdrrec.destnet.point := 0;
end;
with msgarearec.msgrec do
begin
if (typ in [localmail,allmail]) then
msghdrrec.orignet := msghdrrec.destnet;
if (typ in [echomail,netmail]) then
addbeginlines else
makedate;
if (typ = echomail) then
begin
addendlines;
setbit(5,1,msghdrrec.msgattr); (* echomail pending export *)
end else
if (typ = netmail) then
setbit(1,1,msghdrrec.msgattr); (* netmail pending export *)
end;
inc(msghdrrec.messagelength);
msgtxtbuf[msghdrrec.messagelength] := #0;
seek(msgarearec.txtfile,filesize(msgarearec.txtfile));
blockwrite(msgarearec.txtfile,msgtxtrec,msghdrrec.messagelength,numwrote);
if (numwrote <> msghdrrec.messagelength) then
begin
seek(msgarearec.txtfile,msghdrrec.startposition);
truncate(msgarearec.txtfile);
filemode := fdenynone + freadonly;
changeaccess;
seek(msgarearec.hdrfile,hdrpos);
seek(msgarearec.txtfile,txtpos);
exit;
end;
if (msghdrrec.prevreply > 0) then
begin
seek(msgarearec.hdrfile,pred(msghdrrec.prevreply));
blockread(msgarearec.hdrfile,msgtmp,1);
while (msgtmp.nextreply > 0) and
(msgtmp.nextreply <> filepos(msgarearec.hdrfile)) and
(msgtmp.nextreply <= filesize(msgarearec.hdrfile)) do
begin
seek(msgarearec.hdrfile,pred(msgtmp.nextreply));
blockread(msgarearec.hdrfile,msgtmp,1);
end;
msgtmp.nextreply := filesize(msgarearec.hdrfile) + 1;
seek(msgarearec.hdrfile,filepos(msgarearec.hdrfile)-1);
blockwrite(msgarearec.hdrfile,msgtmp,1);
msghdrrec.prevreply := filepos(msgarearec.hdrfile);
end;
seek(msgarearec.hdrfile,filesize(msgarearec.hdrfile));
blockwrite(msgarearec.hdrfile,msghdrrec,1,numwrote);
if (numwrote <> 1) then
begin
seek(msgarearec.txtfile,msghdrrec.startposition);
truncate(msgarearec.txtfile);
filemode := fdenynone + freadonly;
changeaccess;
seek(msgarearec.hdrfile,pred(msghdrrec.prevreply));
blockread(msgarearec.hdrfile,msgtmp,1);
msgtmp.nextreply := 0;
seek(msgarearec.hdrfile,pred(msghdrrec.prevreply));
blockwrite(msgarearec.hdrfile,msgtmp,1);
seek(msgarearec.hdrfile,hdrpos);
seek(msgarearec.txtfile,txtpos);
exit;
end;
if (msgarearec.msgrec.typ in [echomail,netmail]) then
begin
tmpboolean := true;
if not fopen(tmpfile,sizeof(boolean),fdenynone + fwriteonly,
configrec.msgpath + 'MSGEXPRT.BBS') then
exit;
seek(tmpfile,msgarearec.msgarea-1);
blockwrite(tmpfile,tmpboolean,sizeof(boolean));
close(tmpfile);
(* MSGEXPRT.BBS tells ezymail/ezynet which areas to scan for mail *)
if (msgarearec.msgrec.typ = echomail) then
echomailentered := true else
netmailentered := true;
end;
addtofastmail;
updatemsgcount;
filemode := fdenynone + freadonly;
changeaccess;
writemessage := filepos(msgarearec.hdrfile);
seek(msgarearec.hdrfile,hdrpos);
seek(msgarearec.txtfile,txtpos);
end;
function readmessage(var msgarearec : msgarearecord;
msgtoread : word;
var msghdrrec : msghdrrecord;
var msgtxtrec;maxread : word;
var numread : word) : boolean;
(* Reads a message from a previously opened message area
msgtoread is the message number to read (record position + 1)
msghdrrec is the header record that will be returned
msgtxtrec is the message text information
maxread is the maximum amount of text in bytes that can be read
numread is the actual amount of text in bytes that is read
If the amount of text read is less than the actual size of the
message, then this procedure will clean up the tail of the message
by inserting a carriage return and adding the null terminator
On error, numread will be 0, indicating no message was read *)
var
msgtxtbuf : array[1..65000] of byte absolute msgtxtrec;
begin
numread := 0;
readmessage := false;
{$I-}
seek(msgarearec.hdrfile,msgtoread-1);
if (ioresult > 0) or (maxread > 65000) then
exit;
blockread(msgarearec.hdrfile,msghdrrec,1);
if (ioresult > 0) then
exit;
seek(msgarearec.txtfile,msghdrrec.startposition);
if (ioresult > 0) then
exit;
blockread(msgarearec.txtfile,msgtxtrec,maxread,numread);
if (ioresult > 0) then
begin
numread := 0;
exit;
end;
if (numread < msghdrrec.messagelength) then
begin
msgtxtbuf[numread-1] := $0D;
msgtxtbuf[numread] := $00;
end;
readmessage := true;
end;
function retlastread(var lastreadfile : file;
userrecord,
messageboard : word) : word;
var
lastrd : word;
begin
seek(lastreadfile,longint(userrecord) * (longint(constant.maxmess) div 16) * longint(sizeof(userslastrecord)) +
(((messageboard - 1) div 16) * sizeof(userslastrecord) + 2) +
(messageboard-1) mod 16 * 2);
blockread(lastreadfile,lastrd,2);
retlastread := lastrd;
end;
procedure writelastread(var lastreadfile : file;
userrecord,
messageboard,
lastread : word);
begin
seek(lastreadfile,longint(userrecord) * (longint(constant.maxmess) div 16) * longint(sizeof(userslastrecord)) +
(((messageboard - 1) div 16) * sizeof(userslastrecord) + 2) +
(messageboard-1) mod 16 * 2);
blockwrite(lastreadfile,lastread,2);
end;
function retcombinedarea(var lastreadfile : file;
userrecord,
messageboard : word) : boolean;
var
comb : word;
begin
seek(lastreadfile,longint(userrecord) * (longint(constant.maxmess) div 16) * longint(sizeof(userslastrecord)) +
((messageboard - 1) div 16) * longint(sizeof(userslastrecord)));
blockread(lastreadfile,comb,2);
retcombinedarea := biton((messageboard-1) mod 16,comb);
end;
procedure getmsgareacount(var msgareacount : msgareacounttype);
var
tmpfile : file;
begin
if fopen(tmpfile,sizeof(word),fdenynone + freadonly,
configrec.msgpath + 'MSGCOUNT.BBS') then
begin
blockread(tmpfile,msgareacount,maxmess);
close(tmpfile);
end;
end;
function lockit(var f : file;var pos : word;var size : longint;locktype : byte) : boolean;
var
regs : registers;
begin
pos := pos * filerec(f).recsize;
size := size * filerec(f).recsize;
regs.ah := $5C;
regs.al := locktype;
regs.bx := filerec(f).handle;
regs.cx := hi(pos);
regs.dx := lo(pos);
regs.si := hi(size);
regs.di := lo(size);
intr($21,regs);
lockit := ((regs.flags and fcarry) = 0) or (regs.ax = 1);
end;
function lock(var f : file;pos : word;size : longint) : boolean;
var
reg : registers;
begin
lock := lockit(f,pos,size,0);
end;
function unlock(var f : file;pos : word;size : longint) : boolean;
var
reg : registers;
begin
unlock := lockit(f,pos,size,1);
end;
begin
assign(msgrecfile,'');
end.